package com.brooks.demo.program.p2;

import java.util.LinkedList;

/**
 * 写一个固定容量同步容器，拥有put和get方法，以及getCount方法，能够支持2个生产者线程以及10个消费者线程的阻塞调用
 *
 * 这里是使用了wait和notifyAll 两个方法，容器数据慢了，生产者就wait，消费者把东西吃完了，就wait，这里因为我使用
 * 了notifyAll 的方法，所以有点小瑕疵，生产者或者消费者会将其他的所有线程都叫醒，虽然不会出什么问题，但是浪费资源。
 * @Author mihutu
 * @Date 2020/10/21 9:46
 * @Version 1.0
 */
public class Demo1<T> {
    final private LinkedList<T> list = new LinkedList<T>();
    /**最多10个元素*/
    final private int MAX = 10;
    private int count;
    public synchronized void put(T t){
        //这里不使用if 是因为我想线程被唤醒的时候再去判断一下元素是否是满的
        while(list.size() == MAX){
            try {
                //容器满了，阻塞，不能添加元素了
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        list.add(t);
        ++count;
        this.notifyAll();
    }
    public synchronized T get(){
        T t = null;
        //这里原因同上
        while(list.size()==0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        t=list.removeFirst();
        count--;
        this.notifyAll();
        return t;
    }

    public static void main(String[] args) {
        Demo1<String> d = new Demo1<>();
        //两个生产者线程
        for(int i=0;i<2;i++){
            new Thread(()->{
                //每个生产25个
                for(int j=0;j<25;j++){
                    d.put(Thread.currentThread().getName()+" "+j);
                }
            },"p"+i).start();
        }
        //10个消费者线程
        for(int i=0;i<10;i++){
            new Thread(()->{
                //每个消费五个
                for(int j=0;j<5;j++){
                    System.out.println(d.get());
                }
            },"c"+i).start();
        }
    }
}
